﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bule.Malbilden.Domain
{
    public class GoalCollection : List<DayNutritionGoal>
    {
        public GoalCollection() { }
        public GoalCollection(IList<DayNutritionGoal> list)
        {
            foreach (var item in list)
                this.Add(item);
        }

        public DayNutritionGoal GetLatest()
        {
            if (this.Count == 0)
                return null;

            var query = from DayNutritionGoal goal in this
                        where goal.Date == this.Max(g => g.Date)
                        select goal;

            return query.First();
        }

        public DayNutritionGoal Get(DateTime date)
        {
            if (this.Count == 0)
                return null;

            var query = from DayNutritionGoal goal in this
                        where goal.Date == date.Date
                        select goal;

            if (query.Count() == 0)
                return null;

            return query.First();
        }

        public void AddOrReplace(DayNutritionGoal goal)
        {
            DayNutritionGoal foundGoal = Get(goal.Date);

            if (foundGoal == null)
                this.Add(goal);
            else
            {
                foundGoal.Kcal = goal.Kcal;
                foundGoal.ProteinEnergyPercentage = goal.ProteinEnergyPercentage;
                foundGoal.CarbohydrateEnergyPercentage = goal.CarbohydrateEnergyPercentage;
                foundGoal.FatEnergyPercentage = goal.FatEnergyPercentage;
                foundGoal.FiberWeight = goal.FiberWeight;
            }
        }

        public DayNutritionGoal GetClosest(DateTime date)
        {
            if (this.Count == 0)
                return null;

            DayNutritionGoal closestGoal = Get(date);

            if (closestGoal == null)
            {
                var prevGoal = GetPrevious(date);
                var nextGoal = GetNext(date);

                // If one is null, return the other. Otherwise return the goal with the 
                // date closest to the desired date.
                if (prevGoal == null)
                    closestGoal = nextGoal;
                else if (nextGoal == null)
                    closestGoal = prevGoal;
                else if (date - prevGoal.Date > nextGoal.Date - date)
                    closestGoal = nextGoal;
                else
                    closestGoal = prevGoal;
            }

            return closestGoal;
        }

        private DayNutritionGoal GetPrevious(DateTime date)
        {
            if (this.Count == 0)
                return null;
            
            var query = from DayNutritionGoal goal in this
                        where goal.Date < date
                        orderby goal.Date descending
                        select goal;

            if (query.Count() <= 0)
                return null;

            return query.First();
        }

        private DayNutritionGoal GetNext(DateTime date)
        {
            if (this.Count == 0)
                return null;
            
            var query = from DayNutritionGoal goal in this
                        where goal.Date > date
                        orderby goal.Date ascending
                        select goal;

            if (query.Count() <= 0)
                return null;

            return query.First();
        }
    }
}
